
/***********************************************************************************************************************

                                            无限商店服 - 加强版
                                            作者：Live
                                            编写时间：2024年6月1日-2024年6月3日
                                            大致重要内容：
                                                1. 改进版商店菜单
                                                2. 新方案的无限刷僵尸方法（搭配清理过远僵尸方案）
                                            联系方式：QQ2671098686

                                            更新信息：
                                            v0.2：
                                                1、修复了购买禁用的武器依旧会扣钱的问题
                                                2、禁用了枪械强化的金钱BUFF，因为游戏特性，其会导致玩家金钱变成100
                                                3、修复玩家选择复活到自己时提示后会关掉复活菜单的问题，并且新增在玩家复活后自动打开商店
                                                4、商店主菜单添加常用购买
                                                5、修复错误显示自动步枪下一页选项
                                                6、增加新近战武器：Q弹扳手、法式面包

***********************************************************************************************************************/



/***********************************************************************************************************************

                                                公共变量

***********************************************************************************************************************/

// 插件信息

string author = "Live";
string pluginName = "infiniteModePro 无限商店服插件";
string version = "0.2";

/*
    商店内容设计：

    0、常用
        1、AR15
        2、沙鹰
        3、手榴弹
        4、医疗包
        5、连喷
        6、溶解

    1. 自动步枪
        1. AR15
        2. AK74U
        3. SCAR
        4. ACR
    2. 手枪
        1. 西格绍尔
        2. 沙鹰
        3. 1911
        4. 左轮
        5. 马格南左轮
        6. kg9(自动手枪)
    3. 补给
        1. 医疗包
        2. 血清
        3. 复活甲
        4. 补充子弹
        --------
        1. 全息
        2. 红点
        3. 手电
        4. 消音
        5. 导轨
        6. 倍镜
    4. 喷子
        1. 复合枪
        2. 莫斯伯格
        3. 伯奈利（连喷）
        4. 雷明顿870
        5. 单发双喷
    5. 冲锋枪
        1. mac10
        2. mp5k
    6. 近战
        1. 卡巴刀
        2. 警棍
        3. 棒球棒
        4. 高尔夫球棍
        5. 斧头
        6. 小锤
        7. 镰刀
        ----------
        1. 键盘
        2. 撬棍
        3. 班琴
        4. 扳手
        5. 吉他
        6. 铁棒
        7. 砍刀
        ---------
        1. 大锤
        2. Q弹扳手

    7. 半自动长枪
        1. 加兰德
        2. 勃朗宁
        3. 雷明顿700
    8. 特殊
        1. 榴弹枪
        2. 手榴弹
        3. 喷火器
        4. 弓
        5. 弩
        6. 遥控炸弹
        7. 便携式手电
        --------
        1. 荧光棒
    9. 枪械强化
        1. 双倍伤害
        2. 燃烧
        3. 溶解
        4. 爆炸
        5. 金钱
    10. 关卡道具
        1. 钳子
        2. 防毒面具
        3. 灭火器
        4. 钥匙
        5. 卡片
        6. 喷灯（焊枪）
    11. 人物装扮
        1. 特警模型
        2. 圣诞帽
        3. 南瓜头

    .....

*/
dictionary menuList = {

    {"Menu_Main__1",array<string> = {"@主菜单1@\n==作者：Live==","常用","自动步枪","手枪","补给","霰弹枪","冲锋枪","近战"}},
    {"Menu_Main__1_Value",array<string> = {"","Menu_Usua","Menu_Rifle","Menu_Pistol","Menu_Supply__1","Menu_Shotgun","Menu_SubmachineGun","Menu_ColdWeapon__1"}},

    {"Menu_Main__2",array<string> = {"@主菜单2@","半自动长枪","特殊","枪械强化","关卡道具","人物装扮"}},
    {"Menu_Main__2_Value",array<string> = {"","Menu_semiAutomatic","Menu_Special__1","Menu_Evolution","Menu_Prop","Menu_dressUp"}},

    {"Menu_Usua",array<string> = {"@常用@","AR15","沙鹰","手雷","医疗包","连喷","溶解","手电"}},
    {"Menu_Usua_Value",array<string> = {"","ar15","handcannon","Grenade","firstaid","autoshotgun","",""}},
    {"Menu_Usua_Money",array<int> = {,800,1500,150,100,1000,10000,75}},
    
    {"Menu_Rifle",array<string> = {"@自动步枪@","AR15","AK74U","SCAR","ACR"}},
    {"Menu_Rifle_Value",array<string> = {"","ar15","ak74","scar","acr"}},
    {"Menu_Rifle_Money",array<int> = {,800,700,1200,900}},
    
    {"Menu_Pistol",array<string> = {"@手枪@","西格绍尔","沙鹰","1911","左轮","357马格南","kg9(自动手枪)"}},
    {"Menu_Pistol_Value",array<string> = {"","sig","handcannon","1911","revolver","357","kg9"}},
    {"Menu_Pistol_Money",array<int> = {,150,1500,250,300,400,350}},
    
    {"Menu_Supply__1",array<string> = {"@补给1@","医疗包","血清","复活甲","补充弹药"}},
    {"Menu_Supply__1_Value",array<string> = {"","firstaid","inoculator","selfrev","","0"}},
    {"Menu_Supply__1_Money",array<int> = {,100,80,200,100}},
    
    {"Menu_Supply__2",array<string> = {"@补给2@","全息","红点","手电","消音","导轨","倍镜"}},
    {"Menu_Supply__2_Value",array<WeaponAttachment> = {,k_eSightHolo,k_eSightRedDot,k_eFlashlight,k_eSilencer,k_eRailMod,k_eSightScope}},
    {"Menu_Supply__2_Money",array<int> = {,175,160,75,100,200,140}},
    
    {"Menu_Shotgun",array<string> = {"@霰弹枪@","复合枪","莫斯伯格","伯奈利（连喷）","雷明顿870","单发双喷"}},
    {"Menu_Shotgun_Value",array<string> = {"","overunder","mossberg","autoshotgun","remington870","doublebarrel"}},
    {"Menu_Shotgun_Money",array<int> = {,580,600,1000,800,3000}},
    
    {"Menu_SubmachineGun",array<string> = {"@冲锋枪@","mac10","mp5k"}},
    {"Menu_SubmachineGun_Value",array<string> = {"","mac10","mp5k"}},
    {"Menu_SubmachineGun_Money",array<int> = {,500,400}},
    
    {"Menu_ColdWeapon__1",array<string> = {"@近战1@","卡巴刀","警棍","棒球棒","高尔夫球棍","斧头","小锤","镰刀"}},
    {"Menu_ColdWeapon__1_Value",array<string> = {"","kabar","baton","Baseballbat","Golfclub","FireAxe","Hammer","Scythe"}},
    {"Menu_ColdWeapon__1_Money",array<int> = {,150,400,150,160,220,200,250}},

    {"Menu_ColdWeapon__2",array<string> = {"@近战2@","键盘","撬棍","班卓琴","扳手","吉他","金属球棍","弯刀"}},
    {"Menu_ColdWeapon__2_Value",array<string> = {"","Keyboard","Crowbar","Banjo","Wrench","Guitar","Baseballbat_metal","Machete"}},
    {"Menu_ColdWeapon__2_Money",array<int> = {,150,200,180,170,170,160,200}},
    
    {"Menu_ColdWeapon__3",array<string> = {"@近战3@","大锤","Q弹扳手","法式面包"}},
    {"Menu_ColdWeapon__3_Value",array<string> = {"","sledgehammer","jiggle_wrench","baguette"}},
    {"Menu_ColdWeapon__3_Money",array<int> = {,300,1000,200,}},
    
    {"Menu_semiAutomatic",array<string> = {"@半自动长枪@","加兰德","勃朗宁","雷明顿"}},
    {"Menu_semiAutomatic_Value",array<string> = {"","M1garand","BLR","Sniper"}},
    {"Menu_semiAutomatic_Money",array<int> = {,550,500,600}},
    
    {"Menu_Special__1",array<string> = {"@特殊1@","榴弹枪","手榴弹","喷火器","弓","弩","遥控炸弹","便携式手电"}},
    {"Menu_Special__1_Value",array<string> = {"","grenadelauncher","Grenade","flamethrower","compbow","crossbow","Ied","plight"}},
    {"Menu_Special__1_Money",array<int> = {,18000,150,3000,900,500,600,50}},
    
    {"Menu_Special__2",array<string> = {"@特殊2@","荧光棒"}},
    {"Menu_Special__2_Value",array<string> = {"","glowstick"}},
    {"Menu_Special__2_Money",array<int> = {,1}},
    
    {"Menu_Evolution",array<string> = {"@枪械强化","双倍伤害","燃烧","溶解","爆炸","金钱","手电"}},
    {"Menu_Evolution_Value",array<WeaponUpgrade> = {,k_eDoubleDamage,k_eFireDamage,k_eDissolve,k_eExplosive,k_eMoneyBoost,k_eFlashlight}},
    {"Menu_Evolution_Money",array<int> = {,5500,8500,10000,12000,13000,1000}},
    
    {"Menu_Prop",array<string> = {"@关卡道具@","钳子","防毒面具","灭火器","钥匙","卡片","喷灯（焊枪）"}},
    {"Menu_Prop_Value",array<string> = {"","boltcutter","gasmask","extinguisher","key","keycard","torch"}},
    {"Menu_Prop_Money",array<int> = {,10000,10000,10000,10000,10000,10000}},
    
    {"Menu_dressUp",array<string> = {"@人物装扮","特警模型","圣诞帽","南瓜头"}},
    {"Menu_dressUp_Value",array<string> = {}}
};

// 金币存储变量
array<int> moneyList(16);

// 当前玩家
array<int> playerList(16);

// 数据库连接
CSQLConnection@ gMainConnection = null;

// 是否上帝
bool isGod = false;

// 僵尸常量
int zombieC = 0;

// 商店价格倍率
float mf = 0.05;

// 每人多少只僵尸
int zf = 10;

// 过关后奖励多少
int reward = 1000;



/***********************************************************************************************************************

                                                插件初始化

***********************************************************************************************************************/

void OnPluginInit()
{
    // 设置插件信息
    PluginData::SetAuthor(author);
    PluginData::SetName(pluginName);
    PluginData::SetVersion(version);

    // 加载后提示信息
    ThePresident.InfoFeed("插件:"+pluginName+"| 版本:"+version+"| 作者:"+author,false);

    /******************************************
                    钩子声明
    *******************************************/

    // 玩家进入游戏后
    Events::Player::OnPlayerConnected.Hook( @OnPlayerConnected );
    // 玩家说
    Events::Player::PlayerSay.Hook( @PlayerSay );
    // 玩家执行菜单命令
    Events::Player::OnMenuExecuted.Hook( @OnMenuExecuted );
    // 当僵尸出生后
    Events::Infected::OnInfectedSpawned.Hook( @OnInfectedSpawned );
    // 当从随机池创建物品时
    Events::ThePresident::OnRandomItemSpawn.Hook( @OnRandomItemSpawn );
    // 实体掉落
    Events::Player::OnEntityDropped.Hook( @OnEntityDropped );
    // 当玩家被杀死后
    Events::Player::OnPlayerKilledPost.Hook( @OnPlayerKilledPost );
    // 当玩家断开连接后
    Events::Player::OnPlayerDisconnected.Hook( @OnPlayerDisconnected );
    // 丧尸死亡后
    Events::Infected::OnInfectedKilled.Hook( @OnInfectedKilled );
    // 当玩家逃脱
    Events::Player::OnPlayerEscape.Hook( @OnPlayerEscape );
    // 当玩家抵达安全区
    Events::Player::OnPlayerReachSafeZone.Hook( @OnPlayerReachSafeZone );
    // 当玩家离开安全区
    Events::Player::OnPlayerLeftSafeZone.Hook( @OnPlayerLeftSafeZone );
    // 当回合终止时
    Events::ThePresident::OnTerminateRound.Hook( @OnTerminateRound );

    // 连接数据库
    ConnectToDB();

    // 地图开始 
    ThePresident_OnMapStart();
    
}

/***********************************************************************************************************************

                                                    数据库

***********************************************************************************************************************/


/******************************************
                连接数据库
*******************************************/
void ConnectToDB()
{
    // SQL Connection info
    string strSQLHost = "localhost"; // Our hostname
    int iPort = 0; // if iPort is 0, then it will use default MySQL port
    string strSQLUser = "root"; // Our username
    string strSQLPass = "lingfeng"; // Our password
    string strSQLDB = "contagion"; // Our database

    // Create our connection
    SQL::Connect( strSQLHost, iPort, strSQLUser, strSQLPass, strSQLDB, OnSQLConnect );
}

void OnSQLConnect( CSQLConnection@ pConnection )
{
    if ( pConnection.Failed() ) {
        ThePresident.InfoFeed("数据库连接失败！",false);
    }
    
    @gMainConnection = pConnection;
    ThePresident.InfoFeed("数据库连接成功！",false);
    Chat.PrintToConsole(all, "{green}数据库连接成功！");
    Log.PrintToServerConsole(LOGTYPE_INFO, "Database connected...");
}

// 当插件卸载
void OnPluginUnload()
{
    // 关闭数据库连接
    SQL::Disconnect(gMainConnection);
}

// 地图关闭时关闭连接
void OnMapShutdown()
{
    saveALLMoney();
	SQL::Disconnect( gMainConnection );
}

/******************************************
            保存所有玩家金币
*******************************************/
void saveALLMoney(){
    // 保存所有玩家的当前金币
    playerList = Utils.CollectPlayers();
    for(uint i=0;i<playerList.length();i++){
        CTerrorPlayer@ pPlayer = ToTerrorPlayer(playerList[i]);
        string steamid = Utils.Steam64ToSteam32(pPlayer.GetSteamID64());
        string sql_saveMoney = "update `record` set money = "+pPlayer.GetScore()+" where steamid = '"+steamid+"';";
        SQL::SendQuery( gMainConnection, sql_saveMoney);
    }
    Chat.PrintToChat(all,"{green}[数据库]:{hotpink}已保存所有玩家金币值");
}


// 地图初始化时，重新连接
void OnMapInit()
{
	@gMainConnection = null;
	ConnectToDB();
}


/***********************************************************************************************************************

                                                    钩子实现

***********************************************************************************************************************/

/******************************************
                当玩家说话
*******************************************/
HookReturnCode PlayerSay(CTerrorPlayer@ pPlayer, CASCommand@ pArgs)
{

    /******************************************
                字符串分割处理
    *******************************************/
    string arg = pArgs.Arg( 1 );
	string arg1 = "";
	string arg2 = "";

	// 切分字符串(这样就可以用空格传一个命令参数了)
	int subIndex = arg.findFirst(" ",0);
	if(not (subIndex < 0)){
		arg1 = arg.substr(0,subIndex);
		arg2 = arg.substr(subIndex+1,-1);
		//Chat.PrintToChat(all,""+arg1+"|"+arg2);
	}else{
		arg1 = arg;
	}

    /******************************************
                    普通玩家指令
    *******************************************/

    if( arg1=="!b"||arg1=="!buy"||arg1=="！buy" ){

        /******************************************
                        商店
        *******************************************/
        openMenuByName("Menu_Main__1",pPlayer);
        Chat.HintMessagePlayer(pPlayer, "局内金钱:"+pPlayer.GetScore(), Color("#ffffff"));

    }else if(arg1=="!cz"){

        /******************************************
                        查询僵尸数量
        *******************************************/
        Chat.PrintToChat(pPlayer,"当前僵尸数量："+Utils.CollectInfected().length());

    }else if(arg1=="!fh"){

        /******************************************
                        复活
        *******************************************/
        if(arg2==""){
            Open_PlayerShop_Tele(pPlayer);
        }
    }
    
    /******************************************
                    管理员指令
    *******************************************/
    if(AdminSystem.AdminExist(pPlayer)){

        if(arg1=="!suo"){

            /******************************************
                        僵尸锁人
            *******************************************/
            if( ThePresident.IsHordeMode() ){
                ThePresident.StopHordeMode();
                Chat.PrintToChat( all,"{hotpink}Horde模式已关闭" );                    
            }else{
                ThePresident.BeginHordeMode();
                Chat.PrintToChat( all,"{hotpink}Horde模式已启动（全局锁人）" );
            } 

        }else if(arg1=="!testjoin"){

        /******************************************
                        测试加入
        *******************************************/
			playerList = Utils.CollectPlayers();
			for(uint i = 0;i<playerList.length();i++){
				CBasePlayer@ pPlayer = ToBasePlayer(playerList[i]);
				DB_addPlayer(pPlayer);
			}
			Chat.PrintToChat(all,"成功同步所有玩家金币");

		}else if( Utils.StrEql( arg1, "!g" ) ){

            /******************************************
                        全员上帝
            *******************************************/
            CASConVarRef@  god = ConVar::Find( "god" );
            if(god is null) return HOOK_CONTINUE;
            if(isGod){
                god.SetValue("0");
                Chat.PrintToChat( pPlayer,"{hotpink}全员无敌已关闭");
            }else{
                god.SetValue("1");
                Chat.PrintToChat( pPlayer,"{hotpink}全员无敌已开启");
            }
            isGod = !isGod;

        }else if(arg1 == "!give"){

            /******************************************
                            刷枪
            *******************************************/
            if(not Utils.StrEql( arg2, "" )){
                pPlayer.GiveWeapon(arg2);
            }else{
                Chat.PrintToChat(pPlayer,"需要输入武器名");
            }

        }else if(arg1 == "!z"){
            
            /******************************************
                            刷僵尸
            *******************************************/
            if( not Utils.StrEql( arg2, "" ) ){
                ThePresident.SpawnZombies(parseInt(arg2,10,0));
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"生成了"+arg2+"只丧尸");
            }else{
                Chat.PrintToChat(pPlayer,"需要输入僵尸数量");
            }

        }else if(arg1 == "!zc"){
    
            /******************************************
                        僵尸常量
            *******************************************/
            if( not Utils.StrEql( arg2, "" ) ){
                //ThePresident.SetSpawnConstantFlags(ZSF_FORCED_NEAR_SPAWN);
                //ThePresident.SetSpawnZombiesConstant(parseInt(arg2,10,0));
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"设置丧尸常量"+arg2+"只");
                zombieC = parseInt(arg2,10,0);
            }else{
                Chat.PrintToChat(pPlayer,"需要输入僵尸数量");
            }

        }else if(arg1 == "!zac"){

            /******************************************
                        僵尸增加常量
            *******************************************/
            if( not Utils.StrEql( arg2, "" ) ){
                ThePresident.SetSpawnConstantFlags(ZSF_FORCED_NEAR_SPAWN);
                ThePresident.SpawnZombiesConstant(parseInt(arg2,10,0));
                Chat.PrintToChat(all,"{hotpink}管理员"+pPlayer.GetPlayerName()+"设置丧尸增加常量"+arg2+"只");
            }else{
                Chat.PrintToChat(pPlayer,"需要输入僵尸常量增加数量");
            }

        }else if(arg1 == "!ff"){

            /******************************************
                         友伤开关
            *******************************************/
            if( arg2 == "0" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_types 0" );
                Chat.PrintToChat(pPlayer,"{hotpink}开启友伤");
            }else if( arg2 == "1" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_types 1" );
                Chat.PrintToChat(pPlayer,"{hotpink}关闭友伤");
            }else if( arg2 == "2" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_types 2" );
                Chat.PrintToChat(pPlayer,"{hotpink}开启反伤");
            }

        }else if(arg1 == "!ffd"){

            /******************************************
                            自动友伤倍率
            *******************************************/
            CASConVarRef@ casDifficulty = ConVar::Find( "difficulty" );
            string difficulty = casDifficulty.GetValue();
            Chat.PrintToChat(all,"{hotpink}当前难度为："+difficulty);
            // 根据不同难度修改对应参数
            if( difficulty == "0" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_factor_easy "+arg2);
                Chat.PrintToChat(all,"{hotpink}修改友伤系数成功！");
            }else if( difficulty == "1" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_factor_normal "+arg2);
                Chat.PrintToChat(all,"{hotpink}修改友伤系数成功！");
            }else if( difficulty == "2" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_factor_hard "+arg2);
                Chat.PrintToChat(all,"{hotpink}修改友伤系数成功！");
            }else if( difficulty == "3" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_factor_extreme "+arg2);
                Chat.PrintToChat(all,"{hotpink}修改友伤系数成功！");
            }else if( difficulty == "4" ){
                Engine.RunConsoleCommand( "cg_friendly_fire_factor_nightmare "+arg2);
                Chat.PrintToChat(all,"{hotpink}修改友伤系数成功！");
            }
            
        }else if( Utils.StrEql( arg1, "!k" ) ){

            /******************************************
                            管理员指定杀人
            *******************************************/
            if(Utils.StrEql( arg2, "" )){
                int TeamNumber = pPlayer.GetTeamNumber();
                if(TeamNumber == 2){
                    Engine.RunConsoleCommand( "admin slay !" + pPlayer.entindex() );
                    return HOOK_HANDLED;
                }else{
                    Chat.PrintToChat(pPlayer,"{gold}[{green}Server{gold}]{white}:只有做人的时候才能自杀！（Suicide is only possible when in the survivor camp）");
                }
            }else if(arg2 == "all"){
                if( AdminSystem.PlayerHasAccessLevel(pPlayer,LEVEL_SUPERADMIN)){
                    playerList = Utils.CollectPlayers();
                    for(uint i=0;i<playerList.length();i++){
                        CTerrorPlayer@ player = ToTerrorPlayer(playerList[i]);
                        if(player.GetTeamNumber() == TEAM_SURVIVOR){
                            Engine.RunConsoleCommand( "admin slay !" + playerList[i] );
                        }
                    }
                    Chat.PrintToChat(all,"{red}毁灭吧！");
                }else{
                    Chat.PrintToChat(pPlayer,"{hotpink}只有超级管理员能用");
                }
            }

        }else if( Utils.StrEql( arg1, "!fh" ) ){

            /******************************************
                            管理员复活
            *******************************************/
            if( arg2 != "" ) {
                if( arg2 == "all" ){
                    playerList = Utils.CollectPlayers();
                    for(uint i=0;i<playerList.length();i++){
                        CTerrorPlayer@ player = ToTerrorPlayer(playerList[i]);
                        if(player.GetTeamNumber() != TEAM_SURVIVOR){
                            player.ChangeTeam(TEAM_SURVIVOR);
                            player.Respawn();
                            player.SetAbsOrigin(pPlayer.GetAbsOrigin());
                        }
                    }
                    Chat.PrintToChat(all,"管理员复活了所有玩家");
                }else{
                    CTerrorPlayer@ splayer = ToTerrorPlayer( parseInt(arg2,10,0) );
                    if(splayer is null) return HOOK_CONTINUE;
                    // 修改被复活玩家的游戏阵营
                    splayer.ChangeTeam( TEAM_SURVIVOR );
                    // 复活玩家
                    splayer.Respawn();
                    Chat.PrintToChat(all,"{hotpink}管理员使用命令复活了["+splayer.GetPlayerName()+"]");
                }
            }
            
            // else{
            //     // 修改被复活玩家的游戏阵营
            //     pPlayer.ChangeTeam( TEAM_SURVIVOR );
            //     // 复活玩家
            //     pPlayer.Respawn();
            // }

        }else if(arg1=="!mf"){
            if(arg2!=""){
                mf = Utils.StringToFloat(arg2);
                Chat.PrintToChat(pPlayer,"修改倍率为"+mf);
            }
        }else if(arg1=="!zf"){
            if(arg2!=""){
                zf = Utils.StringToInt(arg2);
                Chat.PrintToChat(pPlayer,"每个人刷僵尸"+zf);
                setZombieC();
            }
        }else if(arg1=="!re"){
            if(arg2!=""){
                reward = Utils.StringToInt(arg2);
                Chat.PrintToChat(all,"已设置过关奖励金币为："+reward);
            }
        }else if(arg1 == "!zcloff"){
			
		}else if(arg1 == "!zclon"){
			
		}
    }

    return HOOK_CONTINUE;
}

/******************************************
            根据指定名称打开菜单
*******************************************/
void openMenuByName(string menuName,CTerrorPlayer@ pPlayer){
    Menu pMenu;
    pMenu.SetTitle(cast<array<string>>(menuList[menuName])[0]);
    pMenu.SetID(menuName);

    array<string> itemArray = cast<array<string>>(menuList[menuName]);

    array<int> itemMoney;
    if( !Utils.StrContains("主菜单",itemArray[0]) ){
        itemMoney = cast<array<int>>(menuList[menuName+"_Money"]);
    }
    
    fillItem(pMenu,itemArray,itemMoney,pPlayer);
}

/******************************************
            菜单的填充方法
*******************************************/
void fillItem(Menu pMenu,array<string> itemArray,array<int> itemMoney,CTerrorPlayer@ pPlayer){
    if( itemMoney != {} ){
        for(uint i=1;i<itemArray.length();i++){
            pMenu.AddItem(itemArray[i]+" $"+itemMoney[i]*mf);
        }
    }else{
        for(uint i=1;i<itemArray.length();i++){
            pMenu.AddItem(itemArray[i]);
        }
    }

    if( Utils.StrContains("1",itemArray[0]) || itemArray[0] == "@近战2@"){
        pMenu.SetNext( true );
    }else if(Utils.StrContains("2",itemArray[0])){
        //pMenu.SetBack( true );
    }
    if(itemArray[0]!="@主菜单1@\n==作者：Live==")
        pMenu.SetBack( true );
    pMenu.Display(pPlayer,-1);
}

/******************************************
                菜单执行
*******************************************/
HookReturnCode OnMenuExecuted(CTerrorPlayer@ pPlayer, const string &in szID, int &in iValue)
{

    /******************************************
                翻页
    *******************************************/
    switch(iValue){
        case 8:
        {
            if( ! (Utils.StrContains("2", szID) || Utils.StrContains("3", szID)) )
                openMenuByName("Menu_Main__1",pPlayer);
            else
                backOrNext(szID,pPlayer,false);
            break;
        }
        case 9:
        {
            backOrNext(szID,pPlayer,true);
            break;
        }
    }

    /******************************************
            如果是主菜单，就打开子菜单
    *******************************************/
    if( Utils.StrContains("Menu_Main", szID) ){
        switch( iValue ){
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7: 
            {
                string menuName = cast<array<string>>(menuList[szID+"_Value"])[iValue];
                Chat.PrintToChat(pPlayer,menuName);
                openMenuByName(menuName,pPlayer);
                break;
            }
        }
    }else if(Utils.StrContains("Menu_PlayerShop_Tele_Select", szID)){

    /******************************************
                        复活菜单
    *******************************************/
        // 得到下标
        CASCommand@ arg = StringToArgSplit(szID, ";");
        int index =  Utils.StringToInt(arg.Arg(1));
        if(iValue == 8){
            // 如果是0则第一页，返回就是返回玩家商店
            if( index != 0 )
                Menu_PlayerShop_Tele(pPlayer,index-7);
        }else if(iValue == 9){
            Menu_PlayerShop_Tele(pPlayer,index+7);
        }else if(iValue>0 && iValue<8){
            iValue = iValue + index;
            if( pPlayer.GetTeamNumber() != TEAM_SURVIVOR ){
                int pPlayerIndex = playerList[iValue-1];
                if(pPlayerIndex == pPlayer.entindex()){
                    Chat.PrintToChat(pPlayer,"{hotpink}请选择除自己之外的人");
                }else{
					CBasePlayer@ telePlayer = ToBasePlayer(pPlayerIndex);
					// 判断所选择的玩家是否是人类
					if(telePlayer.GetTeamNumber() == TEAM_SURVIVOR){
						// 修改被复活玩家的游戏阵营
						pPlayer.ChangeTeam( TEAM_SURVIVOR );
						// 复活玩家
						pPlayer.Respawn();
						// 得到被选择玩家的位置
						Vector teleV = telePlayer.GetAbsOrigin();
						// 将复活玩家传送过去
						pPlayer.SetAbsOrigin(teleV);
						Chat.PrintToChat(all,"{hotpink}"+pPlayer.GetPlayerName()+"复活了自己到"+telePlayer.GetPlayerName());
                        // 帮玩家打开商店
                        openMenuByName("Menu_Main__1",pPlayer);
                        return HOOK_CONTINUE;
					}else{
						Chat.PrintToChat(pPlayer,"{hotponk}请选择一个人类");
					}
                }
            }else{
                Chat.PrintToChat(pPlayer,"{hotpink}人死才能复生");
            }
            Open_PlayerShop_Tele(pPlayer);
        }


    }else if(Utils.StrContains("Menu_Usua", szID)){
        /******************************************
                           常用商店
        *******************************************/

        bool isSuccess = true;
        float value = cast<array<int>>(menuList[szID+"_Money"])[iValue] * mf;

        switch(iValue){
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            {
                if( pPlayer.GetScore() - value > 0){
                    isSuccess = pPlayer.GiveWeapon(cast<array<string>>(menuList[szID+"_Value"])[iValue]);
                }else{
                    Chat.PrintToChat(pPlayer,"{hotpink}钱不够");
                    isSuccess = false;
                }
                break;
            }
            case 6:
            {
                CBaseEntity@ baseWeapon = pPlayer.GetCurrentWeapon();
                CTerrorWeapon@ weapon = ToTerrorWeapon(baseWeapon);
                weapon.UpgradeModule(SET, k_eDissolve);
                Chat.PrintToChat(pPlayer,"强化成功！");
                break;
            }
            case 7:
            {
                CBaseEntity@ baseWeapon = pPlayer.GetCurrentWeapon();
                CTerrorWeapon@ weapon = ToTerrorWeapon(baseWeapon);
                weapon.SetAttachment(k_eFlashlight,true);
                Chat.PrintToChat(pPlayer,"升级成功！请切换武器/手机刷新");
                break;
            }
        
        }

        if(isSuccess)
            pPlayer.AddScore(-value);

        openMenuByName(szID,pPlayer);

    }else{
    /******************************************
                    其它商店子菜单就购买
    *******************************************/
        // 得到物品价值
        int item_Money = cast<array<int>>(menuList[szID+"_Money"])[iValue];
        // 判断金币是否够
        if(pPlayer.GetScore() < item_Money*mf){
            Chat.PrintToChat(pPlayer,"{hotpink}金额不足！购买失败");
        }else{

            bool isSuccess = true;

            CBaseEntity@ baseWeapon = pPlayer.GetCurrentWeapon();
            CTerrorWeapon@ weapon = ToTerrorWeapon(baseWeapon);

            if(szID == "Menu_Supply__2"){

                WeaponAttachment attachment = cast<array<WeaponAttachment>>(menuList[szID+"_Value"])[iValue];
                weapon.SetAttachment(attachment,true);
                Chat.PrintToChat(pPlayer,"升级成功！请切换武器/手机刷新");

            }else if(szID == "Menu_Evolution"){
                
                WeaponUpgrade UpgradeMod = cast<array<WeaponUpgrade>>(menuList[szID+"_Value"])[iValue];
                if( UpgradeMod == k_eExplosive ){
                    Chat.PrintToChat(pPlayer,"因模式平衡性考虑，暂时关闭购买");
                    isSuccess = false;
                }else if( UpgradeMod == k_eMoneyBoost){
                    Chat.PrintToChat(pPlayer,"这玩意游戏特性会让钱变100,会出现BUG,关闭购买");
                    isSuccess = false;
                }else{
                    weapon.UpgradeModule(SET, UpgradeMod);
                    Chat.PrintToChat(pPlayer,"强化成功！");
                }

            }else{
                switch( iValue ){
                    
                    case 1:
                    case 2:
                    case 3:
                    case 4:
                    case 5:
                    case 6:
                    case 7: 
                    {
                        string menuValue = cast<array<string>>(menuList[szID+"_Value"])[iValue];
                        if( menuValue == "grenadelauncher" ){
                            Chat.PrintToChat(pPlayer,"因模式平衡性考虑，暂时关闭购买该武器");
                            isSuccess = false;
                            break;
                        }
                        Chat.PrintToChat(pPlayer,menuValue);
                        if(!pPlayer.GiveWeapon(menuValue))
                            isSuccess = false;
                        break;
                    }
                }
            }
            // 扣除金币
            if( isSuccess )
                pPlayer.AddScore(-item_Money*mf);
        }
        // 重新打开菜单（防止开菜单疲惫）
        openMenuByName(szID,pPlayer);
    }

    return HOOK_CONTINUE;
}

/******************************************
                翻页核心逻辑
*******************************************/
void backOrNext(string szID,CTerrorPlayer@ pPlayer,bool flag){
    int subIndex = szID.findFirst("__",0);
    string menuName;
    int newNum;
    if(not (subIndex < 0)){
        menuName = szID.substr(0,subIndex+2);
        string num = szID.substr(subIndex+2,-1);
        if(flag)
            newNum = Utils.StringToInt(num)+1;
        else
            newNum = Utils.StringToInt(num)-1;
        openMenuByName(menuName+newNum,pPlayer);
    }
}



/******************************************
                当玩家进入游戏后
*******************************************/
HookReturnCode OnPlayerConnected(CTerrorPlayer@ pPlayer)
{
    // 欢迎玩家
    Chat.PrintToChat(pPlayer,"{gold}[{green}服务器{gold}]{white}:{green}本服务器为无限商店服：僵尸无限、子弹无限、!b/!buy开启商店,交流群请加392635015");

    // 数据库注册玩家
    DB_addPlayer(pPlayer);

    setZombieC();

    return HOOK_CONTINUE;
}

HookReturnCode OnPlayerDisconnected(CTerrorPlayer@ pPlayer)
{
    setZombieC();
    return HOOK_CONTINUE;
}

void setZombieC(){

    // 查询当前玩家人数
    playerList = Utils.CollectPlayers();
    int playerNum = playerList.length();
    Chat.PrintToChat(all,"当前玩家人数为：{gold}"+playerNum);
    // 根据玩家数设定僵尸常量
    int Num = playerNum * zf;
    if( Num < 90 )
        zombieC = playerNum * zf;
    else
        zombieC = 90;
    Chat.PrintToChat(all,"僵尸常量已设置为：{gold}"+zombieC+"(每人"+zf+"个)");
}

/******************************************
                插入玩家到数据库
*******************************************/

void DB_addPlayer(CTerrorPlayer@ pPlayer){
    string steamid = Utils.Steam64ToSteam32(pPlayer.GetSteamID64());
    // 创建数据库信息
    string sql_addPlayer = "INSERT INTO `record`(steamid,name) "
    "SELECT '"+steamid+"','"+pPlayer.GetPlayerName()+"' FROM DUAL "
    "WHERE NOT EXISTS("
	"SELECT steamid "
	"FROM `record` "
	"WHERE steamid = '"+steamid+"'"
    ");";
    //Chat.PrintToChat(all,sql_addPlayer);
    SQL::SendQuery( gMainConnection, sql_addPlayer, addPlayer );

    // 设置玩家金币，同步
    string sql_queryPlayer = "select * from `record` where steamid = '"+steamid+"';";
    SQL::SendQuery( gMainConnection, sql_queryPlayer, setPlayerMoney );
}

void addPlayer(IMySQL@ pQuery){
    // If our query is null, then it failed.
    if ( pQuery is null ) return;

    // That means the table does not exist. Let's create our table then.
    if ( !pQuery.Failed() )
    {
        //Chat.PrintToChat(all,"添加玩家信息成功！");
    }else{
        //Chat.PrintToChat(all,"添加玩家信息失败！");
    }
}

/******************************************
                设置玩家金币
*******************************************/
void setPlayerMoney(IMySQL@ pQuery){
    if( pQuery is null ) return;
    if( !pQuery.Failed() ){
        string steamid = SQL::ReadResult::GetString( pQuery, "steamid" );
        CTerrorPlayer@ pPlayer = GetPlayerBySteamID(steamid);
        // 归 0
        if( pPlayer.GetScore()!=0 )
            pPlayer.AddScore(-pPlayer.GetScore());
        int money = SQL::ReadResult::GetInt( pQuery, "money" );
        pPlayer.AddScore(money);
        Log.PrintToServerConsole(LOGTYPE_INFO, "money---Synchronized");
    }
}

/******************************************
                地图开始
*******************************************/
void ThePresident_OnMapStart(){

    // 无限刷
    MAXZOMBIE();
    // 距离删除
    deleteZ();

    // 服务器中文名
    Engine.RunConsoleCommand( "hostname [CN.Live] 特殊 | 无限模式（商店）infinite QQ群392635015");
    // 设置难度
    Engine.RunConsoleCommand( "Difficulty 2");
    // 执行回合开始
    ThePresident_OnRoundStart();

}


/******************************************
                回合开始
*******************************************/
void ThePresident_OnRoundStart()
{
    // 无感染
    Engine.RunConsoleCommand( "cg_infection_disabled 1" );
    // 无人类僵尸
    Engine.RunConsoleCommand( "cg_zombie_ai_only 1" );
    
    // 无限子弹
    CASConVarRef@ sv_infinite_collected_ammo = ConVar::Find( "sv_infinite_collected_ammo" );
    sv_infinite_collected_ammo.SetValue("1");
    Chat.PrintToChat(all,"{hotpink}无限备弹开启");
    // 无限体力
    CASConVarRef@ infiniteStamina= ConVar::Find( "sv_infinite_stamina" );
    infiniteStamina.SetValue("1");
    Chat.PrintToChat( all,"{hotpink}无限体力开启" );

    ThePresident.BeginHordeMode();
    Chat.PrintToChat( all,"{hotpink}Horde模式已启动（全局锁人）" );
}

/******************************************
                玩家逃离
*******************************************/
HookReturnCode OnPlayerEscape(CTerrorPlayer@ pPlayer)
{
    // If the player escapes, I need to make some records
    pPlayer.AddScore(reward);
    Chat.PrintToChat(all,"已奖励玩家{green}["+pPlayer.GetPlayerName()+"]{gold}"+reward+"金币");
    //Chat.PrintToChat(all,"执行了逃脱hook");
    updateEscape(pPlayer);
	return HOOK_CONTINUE;
}

/******************************************
                保存金币
*******************************************/
void saveMoney(CTerrorPlayer@ pPlayer){
    string steamid = Utils.Steam64ToSteam32(pPlayer.GetSteamID64());
    string sql_saveMoney = "update `record` set money = "+pPlayer.GetScore()+" where steamid = '"+steamid+"';";
    SQL::SendQuery( gMainConnection, sql_saveMoney);
}

/******************************************
            更新（修改）玩家逃脱次数
*******************************************/
void updateEscape(CTerrorPlayer@ pPlayer){
    string steamid = Utils.Steam64ToSteam32(pPlayer.GetSteamID64());
    string sql_updateEscapeCount = "update `record` set escapeCount = escapeCount+1 where steamid = '"+steamid+"';";
    SQL::SendQuery( gMainConnection, sql_updateEscapeCount);
}

// 是否已保存
bool isSave = false;

/******************************************
                玩家到达安全区
*******************************************/
HookReturnCode OnPlayerReachSafeZone(CTerrorPlayer@ pPlayer)
{
    Chat.PrintToChat(all,"玩家{green}"+pPlayer.GetPlayerName()+"抵达安全区");
    if( !isSave ){
        saveALLMoney();
        isSave = true;
    }
	return HOOK_CONTINUE;
}

/******************************************
                玩家离开安全区
*******************************************/
HookReturnCode OnPlayerLeftSafeZone(CTerrorPlayer@ pPlayer)
{
    Chat.PrintToChat(all,"玩家离开安全区");
	return HOOK_CONTINUE;
}

/******************************************
                回合终止
*******************************************/
HookReturnCode OnTerminateRound(int iTeam)
{
    saveALLMoney();
	return HOOK_CONTINUE;
}

/***********************************************************************************************************************

                                                    无限刷核心

***********************************************************************************************************************/
void MAXZOMBIE(){
    // 每隔5秒检测一次(放前面，防止下面代码执行失败就停掉了)
    Schedule::Task(1.0f,"MAXZOMBIE");
    // 如果玩家人数大于0了，就开始刷起来
    if( Utils.CollectPlayers().length() > 0 ){
        Log.PrintToServerConsole(LOGTYPE_INFO,"-------------------checking--------------");

        /******************************************
                （方案一：已废弃）用僵尸生成区去刷僵尸
        *******************************************/

        // 去找僵尸生成区
        // string name = "trigger_zombie_spawns";
        // CBaseEntity @pEnt = FindEntityByClassname( null, name );
        // while( pEnt !is null)
        // {
        //     // 如果 现在的僵尸数量 < 我们设置的僵尸常数数量
        //     int num = Utils.CollectInfected().length();
        //     if( num < zombieC ){
                
        //         Log.PrintToServerConsole(LOGTYPE_INFO,"--------"+num+"--------"+zombieC+"--------");

        //         // 玩家列表中随机拿取一个玩家的索引值
        //         int index = Math::RandomInt(1,Utils.CollectPlayers().length());
        //         //转化为实体对象
        //         CTerrorPlayer@ pPlayer = ToTerrorPlayer(index);
                
        //         if( pPlayer.GetTeamNumber() == TEAM_SURVIVOR ){

        //             //Log.PrintToServerConsole(LOGTYPE_INFO,"--------getPlayer--------"+pPlayer.GetPlayerName()+"--------");

        //             // 得到这个玩家的坐标
        //             Vector ve = pPlayer.GetAbsOrigin();

        //             // 然后去测量这个僵尸生成区与这个玩家的距离
        //             float jl = Globals.Distance(pEnt.GetAbsOrigin(),ve);
        //             //Log.PrintToServerConsole(LOGTYPE_INFO,"--------player/trigger--------"+jl+"--------");

        //             int distance_respawn = 2;
        //             // 如果距离小于10米
        //             if( Utils.FloatToInt(jl) < distance_respawn*100 ){

        //                 // 在僵尸生成区开始生成僵尸
        //                 ThePresident.SpawnZombiesForceArea(20,pEnt.GetEntityName());
                    
        //             }
        //         }

        //         @pEnt = FindEntityByClassname( pEnt, name );

        //     }else{

        //         Log.PrintToServerConsole(LOGTYPE_INFO,"----------OK---------");
        //         @pEnt = null;

        //     }
        // }

        /******************************************
            （方案二）直接用SpawnZombiesInVolume体积刷
        *******************************************/

        // 随机一个玩家
        int index = Math::RandomInt(1,Utils.CollectPlayers().length());
        //转化为实体对象
        CTerrorPlayer@ pPlayer = ToTerrorPlayer(index);
        int num = Utils.CollectInfected().length();
        Log.PrintToServerConsole(LOGTYPE_INFO,"--------"+num+"--------"+zombieC+"--------");
        // 如果低于设定值
        if( num < zombieC ){
            //在该玩家10米之内狂刷
            float flOffset = 1000.0f;    //Volume size offset
            Vector vPlayer = pPlayer.GetAbsOrigin();    //Player (Volume Center)
            Vector vMinVolume = Vector( vPlayer.x - flOffset, vPlayer.y - flOffset, vPlayer.z - flOffset );    //Spawn Volume - Start
            Vector vMaxVolume = Vector( vPlayer.x + flOffset, vPlayer.y + flOffset, vPlayer.z + flOffset );    //Spawn Volume - End
            ThePresident.SpawnZombiesInVolume(zombieC, vMinVolume, vMaxVolume, false);
        }else{
            Log.PrintToServerConsole(LOGTYPE_INFO,"----------OK---------");
        }
    }
}

/******************************************
                当僵尸出生
*******************************************/
HookReturnCode OnInfectedSpawned(Infected@ pInfected)   
{
    // Vector v = pInfected.GetAbsOrigin();
    // if(ThePresident.PlayersCanSeeThis(v)){
    //     pInfected.SUB_Remove();
    // }
    return HOOK_CONTINUE;
}

/***********************************************************************************************************************

                                                僵尸清理（过远自动删除）
                                                !!!太吃性能了

***********************************************************************************************************************/
// 删除距离玩家非常远的僵尸，防止摸鱼充数卡顿
void deleteZ(){

    // 每10秒检测一次
    Schedule::Task( 10.0f , deleteZ );
    Log.PrintToServerConsole(LOGTYPE_INFO,"-------------check Delete--------------");

    array<int> zombie = Utils.CollectInfected();
    playerList = Utils.CollectPlayers();
    bool needDelete;

    // 遍历
    for( uint i=0;i<zombie.length();i++ ){

        // 默认需要删除，旁边有人就不删除
        needDelete = true;
        CBaseEntity@ base = FindEntityByEntIndex(zombie[i]);


        // 遍历玩家，一旦有距离近的玩家就不删除
        for(uint j=0;j<playerList.length();j++){

            CTerrorPlayer@ pPlayer = ToTerrorPlayer(playerList[j]);

            if( pPlayer.GetTeamNumber() == TEAM_SURVIVOR ){

                Vector ve = pPlayer.GetAbsOrigin();
            
                // 距离
                float jl = Globals.Distance(base.GetAbsOrigin(),ve);
                Log.PrintToServerConsole(LOGTYPE_INFO,"----------Distance-----"+jl+"-------");

                int distance_delete = 15;
                // 如果距离小于10米
                if( Utils.FloatToInt(jl) < distance_delete*100){
                    
                    needDelete = false;
                    break;
                }

            }

        }
        if( needDelete ){
            base.SUB_Remove();
            Log.PrintToServerConsole(LOGTYPE_INFO,"-------------delete Z--------------");
        }
    }
}


/***********************************************************************************************************************

                                                当随机物品被生成时

***********************************************************************************************************************/
// 清除所有枪和子弹(除了任务道具和木板)
HookReturnCode OnRandomItemSpawn(const string &in strClassname, CBaseEntity@ pEntity)
{
    if( Utils.StrContains("weapon_",strClassname) && strClassname != "weapon_boltcutter" 
    &&strClassname != "weapon_extinguisher" && strClassname != "weapon_firstaid" && strClassname != "weapon_gasmask" 
    && strClassname != "weapon_glowstick" && strClassname != "weapon_grenade" && strClassname != "weapon_ied" 
    && strClassname != "weapon_inoculator" && strClassname != "weapon_itemcarry" && strClassname != "weapon_key" 
    && strClassname != "weapon_keycard" && strClassname != "weapon_nailgun" && strClassname != "weapon_torch" 
    && strClassname != "weapon_ied"){
        Log.PrintToServerConsole(LOGTYPE_INFO,"item_delete:"+strClassname);
        pEntity.SUB_Remove();
    }
    if( Utils.StrContains("item_ammo_",strClassname) && strClassname != "item_ammo_barricade" ){
        pEntity.SUB_Remove();
    }
    //Log.PrintToServerConsole(LOGTYPE_INFO,"item_create:"+strClassname);
	return HOOK_CONTINUE;
}


/***********************************************************************************************************************

                                                当实体掉落时
                                                清除掉落的子弹
                                                30秒清除掉落的枪

***********************************************************************************************************************/
HookReturnCode OnEntityDropped(CTerrorPlayer@ pPlayer, CBaseEntity@ pEntity)
{
    if(pEntity.ClassnameIs("item_ammo_*")){
        pEntity.SUB_Remove();
    }else{
        deleteWeapon();
    }
    return HOOK_CONTINUE;
}

/******************************************
                30秒删除武器
*******************************************/
void deleteWeapon(){
    string name = "weapon_*";
    CBaseEntity @base = FindEntityByName( null, name );
    while( base !is null ){
        if( base.GetOwner() is null ){
            // 根据实测，如果不改名，下次又会找到这个枪并重新30秒，所以先改个名
            base.SetEntityName("drop_weapon");
            base.SUB_StartFadeOut(30.0f,false);
        }
        @base = FindEntityByName( base, name );
    }
}

/***********************************************************************************************************************

                                                当玩家被杀
                                                自动打开复活菜单

***********************************************************************************************************************/
HookReturnCode OnPlayerKilledPost(CTerrorPlayer@ pPlayer)
{
    // 杀戮提示信息
    ThePresident.FakeKillFeed("僵尸", pPlayer.GetPlayerName(), "", true, TEAM_ZOMBIE, TEAM_SURVIVOR);
	Open_PlayerShop_Tele(pPlayer);
    return HOOK_CONTINUE;
}


/***********************************************************************************************************************

                                                玩家复活菜单
                                                
***********************************************************************************************************************/
void Open_PlayerShop_Tele(CTerrorPlayer@ pPlayer){
    Menu_PlayerShop_Tele(pPlayer,0);
}

// 玩家传送菜单
void Menu_PlayerShop_Tele(CTerrorPlayer@ pPlayer,int index){
    if (pPlayer is null ) return;
    playerList = Utils.CollectPlayers();
    Menu pMenu;
	pMenu.SetID( "Menu_PlayerShop_Tele_Select;"+index );
	pMenu.SetTitle( "@请选择复活到谁@" );
    // 内容填充方法（填充玩家）
    Player_ItemFill(pPlayer,pMenu,index);
}

// 内容填充方法，从index开始
void Player_ItemFill(CTerrorPlayer@ pPlayer,Menu pMenu,int index){
    // 计数
    int count = 0;
    for(uint i=index;i<playerList.length();i++){
        CBasePlayer@ player = ToBasePlayer(playerList[i]);
        pMenu.AddItem(""+player.GetPlayerName());
        // 因为菜单一页只能有七个
        if(count>6) break;
        count++;
    }
    pMenu.SetBack( true );
    // 如果大于7项，就有下一页按钮
    if(count>6){
        pMenu.SetNext( true );
    }
    pMenu.Display( pPlayer, -1 );
}

HookReturnCode OnInfectedKilled(Infected@ pInfected, CTakeDamageInfo &in DamageInfo)
{
    CBaseEntity@ pAttacker = DamageInfo.GetAttacker();	//获取攻击者信息
    CTerrorPlayer@ pPlayer = ToTerrorPlayer(pAttacker);	//转换攻击者为玩家属性
    pPlayer.AddScore(1);
    Chat.HintMessagePlayer(pPlayer, "局内金钱:"+pPlayer.GetScore(), Color("#ffffff"));
    return HOOK_CONTINUE;
}